#include "utils.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>

// 获取参数数量
size_t GetArgCount(napi_env env, napi_callback_info info) {
    size_t argc = MAX_PARAMS;
    napi_get_cb_info(env, info, &argc, NULL, NULL, NULL);
    return argc;
}

// 从参数中获取数字
double GetNumberFromArgs(napi_env env, napi_callback_info info, int argIndex) {
    size_t argc = MAX_PARAMS;
    napi_value args[MAX_PARAMS];
    napi_get_cb_info(env, info, &argc, args, NULL, NULL);
    
    if (argc <= argIndex) {
        napi_throw_error(env, NULL, "Wrong number of arguments");
        return 0;
    }
    
    napi_valuetype valuetype;
    napi_typeof(env, args[argIndex], &valuetype);
    
    if (valuetype != napi_number) {
        napi_throw_type_error(env, NULL, "Argument must be a number");
        return 0;
    }
    
    double value;
    napi_get_value_double(env, args[argIndex], &value);
    return value;
}

// 从参数中获取整数
int32_t GetInt32FromArgs(napi_env env, napi_callback_info info, int argIndex) {
    size_t argc = MAX_PARAMS;
    napi_value args[MAX_PARAMS];
    napi_get_cb_info(env, info, &argc, args, NULL, NULL);
    
    if (argc <= argIndex) {
        napi_throw_error(env, NULL, "Wrong number of arguments");
        return 0;
    }
    
    napi_valuetype valuetype;
    napi_typeof(env, args[argIndex], &valuetype);
    
    if (valuetype != napi_number) {
        napi_throw_type_error(env, NULL, "Argument must be a number");
        return 0;
    }
    
    int32_t value;
    napi_get_value_int32(env, args[argIndex], &value);
    return value;
}

// 从参数中获取字符串
char* GetStringFromArgs(napi_env env, napi_callback_info info, int argIndex) {
    size_t argc = MAX_PARAMS;
    napi_value args[MAX_PARAMS];
    napi_get_cb_info(env, info, &argc, args, NULL, NULL);
    
    if (argc <= argIndex) {
        napi_throw_error(env, NULL, "Wrong number of arguments");
        return NULL;
    }
    
    napi_valuetype valuetype;
    napi_typeof(env, args[argIndex], &valuetype);
    
    if (valuetype != napi_string) {
        napi_throw_type_error(env, NULL, "Argument must be a string");
        return NULL;
    }
    
    size_t length;
    napi_get_value_string_utf8(env, args[argIndex], NULL, 0, &length);
    char* buffer = (char*)malloc((length + 1) * sizeof(char));
    if (!buffer) return NULL;
    
    napi_get_value_string_utf8(env, args[argIndex], buffer, length + 1, &length);
    return buffer;
}

// 从参数中获取布尔值
bool GetBooleanFromArgs(napi_env env, napi_callback_info info, int argIndex) {
    size_t argc = MAX_PARAMS;
    napi_value args[MAX_PARAMS];
    napi_get_cb_info(env, info, &argc, args, NULL, NULL);
    
    if (argc <= argIndex) {
        napi_throw_error(env, NULL, "Wrong number of arguments");
        return false;
    }
    
    napi_valuetype valuetype;
    napi_typeof(env, args[argIndex], &valuetype);
    
    if (valuetype != napi_boolean) {
        napi_throw_type_error(env, NULL, "Argument must be a boolean");
        return false;
    }
    
    bool value;
    napi_get_value_bool(env, args[argIndex], &value);
    return value;
}

// 从参数中获取数组
napi_status GetArrayFromArgs(napi_env env, napi_callback_info info, 
                            int argIndex, napi_value* result, uint32_t* length) {
    size_t argc = MAX_PARAMS;
    napi_value args[MAX_PARAMS];
    napi_get_cb_info(env, info, &argc, args, NULL, NULL);
    
    if (argc <= argIndex) {
        return napi_invalid_arg;
    }
    
    napi_valuetype valuetype;
    napi_typeof(env, args[argIndex], &valuetype);
    
    if (valuetype != napi_object) {
        return napi_object_expected;
    }
    
    bool is_array;
    napi_is_array(env, args[argIndex], &is_array);
    
    if (!is_array) {
        return napi_array_expected;
    }
    
    *result = args[argIndex];
    return napi_get_array_length(env, *result, length);
}

// 从参数中获取对象
napi_status GetObjectFromArgs(napi_env env, napi_callback_info info, 
                             int argIndex, napi_value* result) {
    size_t argc = MAX_PARAMS;
    napi_value args[MAX_PARAMS];
    napi_get_cb_info(env, info, &argc, args, NULL, NULL);
    
    if (argc <= argIndex) {
        return napi_invalid_arg;
    }
    
    napi_valuetype valuetype;
    napi_typeof(env, args[argIndex], &valuetype);
    
    if (valuetype != napi_object) {
        return napi_object_expected;
    }
    
    *result = args[argIndex];
    return napi_ok;
}

// 创建数字
napi_value CreateNumber(napi_env env, double value) {
    napi_value result;
    napi_create_double(env, value, &result);
    return result;
}

// 创建字符串
napi_value CreateString(napi_env env, const char* value) {
    napi_value result;
    napi_create_string_utf8(env, value, NAPI_AUTO_LENGTH, &result);
    return result;
}

// 创建布尔值
napi_value CreateBoolean(napi_env env, bool value) {
    napi_value result;
    napi_get_boolean(env, value, &result);
    return result;
}

// 创建数组
napi_value CreateArray(napi_env env, size_t length) {
    napi_value result;
    napi_create_array_with_length(env, length, &result);
    return result;
}

// 创建对象
napi_value CreateObject(napi_env env) {
    napi_value result;
    napi_create_object(env, &result);
    return result;
}

// 创建函数
napi_value CreateFunction(napi_env env, const char* name, napi_callback cb) {
    napi_value result;
    napi_create_function(env, name, NAPI_AUTO_LENGTH, cb, NULL, &result);
    return result;
}

// 创建null
napi_value CreateNull(napi_env env) {
    napi_value result;
    napi_get_null(env, &result);
    return result;
}

// 创建undefined
napi_value CreateUndefined(napi_env env) {
    napi_value result;
    napi_get_undefined(env, &result);
    return result;
}

// 设置属性
napi_status SetProperty(napi_env env, napi_value object, 
                       const char* name, napi_value value) {
    napi_value key;
    napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &key);
    return napi_set_property(env, object, key, value);
}

// 获取属性
napi_status GetProperty(napi_env env, napi_value object, 
                       const char* name, napi_value* value) {
    napi_value key;
    napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &key);
    return napi_get_property(env, object, key, value);
}

// 调用函数
napi_value CallFunction(napi_env env, napi_value func, 
                       size_t argc, const napi_value* argv) {
    napi_value global;
    napi_get_global(env, &global);
    napi_value result;
    napi_call_function(env, global, func, argc, argv, &result);
    return result;
}

// 抛出错误
napi_status ThrowError(napi_env env, const char* message) {
    napi_throw_error(env, NULL, message);
    return napi_ok;
}

napi_status ThrowTypeError(napi_env env, const char* message) {
    napi_throw_type_error(env, NULL, message);
    return napi_ok;
}

napi_status ThrowRangeError(napi_env env, const char* message) {
    napi_throw_range_error(env, NULL, message);
    return napi_ok;
}